package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.DeviceDto;
import com.zzyl.entity.Device;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Resource
    Client client;

    @Resource
    private DeviceMapper deviceMapper;

    @Value("${zzyl.aliyun.iotInstanceId}")
    private String iotInstanceId;

    @Override
    public void registerDevice(DeviceDto deviceDto) throws Exception {
        //获取请求
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        //请求中封装地域信息
        request.setIotInstanceId(iotInstanceId);
        //通过request获取响应数据
        RegisterDeviceResponse response = client.registerDevice(request);
        //如果响应成功，则没有当前设备，进行新增设备操作
        if(Boolean.TRUE.equals(response.getBody().getSuccess())){
            //保存位置
            //对象拷贝

            Device device = BeanUtil.toBean(deviceDto, Device.class);
            //设备id
            String iotId = response.getBody().getData().getIotId();
            //设备key
            String productKey = request.getProductKey();
            //昵称
            String nickname = request.getNickname();
            device.setDeviceId(iotId);
            device.setProductId(productKey);
            device.setNoteName(nickname);

            //到iot中查询产品名称
            QueryProductRequest productRequest = new QueryProductRequest();
            productRequest.setIotInstanceId(iotInstanceId);
            productRequest.setProductKey(productKey);
            QueryProductResponse queryProductResponse = client.queryProduct(productRequest);
            String productName = queryProductResponse.getBody().getData().getProductName();
            device.setProductName(productName);
            //判断设备接入的类别
            if(device.getLocationType().equals(0)){
                device.setPhysicalLocationType(-1);
            }
            //是否新增成功
            try{
                //成功，执行添加操作
                deviceMapper.insert(device);
            }catch (Exception e){
                //失败，删除IOT中的设备
                // 该老人/位置已绑定该产品，请重新选择
                DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
                deleteDeviceRequest.setIotInstanceId(iotInstanceId);
                String deviceName = device.getDeviceName();
                deleteDeviceRequest.setDeviceName(deviceName);
                String deviceId = device.getDeviceId();
                deleteDeviceRequest.setIotId(deviceId);
                String productId = device.getProductId();
                deleteDeviceRequest.setProductKey(productId);
                client.deleteDevice(deleteDeviceRequest);
                throw new BaseException("该老人/位置已绑定该产品，请重新选择");
            }
            return;
        }
        //响应信息为false，则设备已经存在，抛出异常信息
        throw new BaseException("设备名称已存在，请重新输入");
    }

    @Override
    public void updateDevice(DeviceDto deviceDto) throws Exception {
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(iotInstanceId);
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo =
                BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response = client.batchUpdateDeviceNickname(request);
        // 保存位置
        if (Boolean.TRUE.equals(response.getBody().getSuccess())) {
            // 保存位置
            Device device = BeanUtil.toBean(deviceDto, Device.class);
            device.setProductId(deviceDto.getProductKey());
            device.setNoteName(deviceDto.getNickname());
            Device device1 = deviceMapper.selectByPrimaryKey(device.getId());
            if (ObjectUtil.isEmpty(device1)) {
                device.setDeviceId(deviceDto.getIotId());
                device.setNoteName(deviceDto.getNickname());
                device.setProductId(deviceDto.getProductKey());
                device.setDeviceId(deviceDto.getIotId());
                deviceMapper.insert(device);
                return;
            }
            try {
                deviceMapper.updateByPrimaryKeySelective(device);
            }catch (Exception e) {
                throw new BaseException("该老人/位置已绑定该产品，请重新选择");
            }
            return;
        }
        throw new BaseException(response.getBody().getErrorMessage());

    }

    @Override
    public PageResponse<DeviceVo> queryDevice(QueryDeviceRequest request) throws Exception {
        //查询设备列表(查询iot中的设备列表数据)
        request.setIotInstanceId(iotInstanceId);
        QueryDeviceResponse queryDeviceResponse = client.queryDevice(request);
        QueryDeviceResponseBody body = queryDeviceResponse.getBody();
        if(Boolean.TRUE.equals(body.getSuccess()) && body.getData() != null){
            //获取设备信息
            List<QueryDeviceResponseBody.QueryDeviceResponseBodyDataDeviceInfo> deviceInfo = body.getData().getDeviceInfo();
            if(CollUtil.isEmpty(deviceInfo)){
                return null;
            }
            //获取设备id（集合）
            List<String> list = deviceInfo.stream().map(
                    QueryDeviceResponseBody.QueryDeviceResponseBodyDataDeviceInfo::getIotId
            ).collect(Collectors.toList());
            //通过设备（集合）查询设备信息 数据库中的设备数据
            List<DeviceVo> devices = deviceMapper.selectByDeviceIds(list);

            //转换一个map : {iotid:设备对象}
            Map<String, DeviceVo> deviceVoMap = devices.stream().collect(Collectors.toMap(DeviceVo::getDeviceId, v -> v));

            //整合数据
            List<DeviceVo> collect = deviceInfo.stream().map(
                    v -> {
                        //对象转换
                        DeviceVo deviceVo = BeanUtil.toBean(v, DeviceVo.class);
                        deviceVo.setDeviceId(v.getIotId());
                        if (ObjectUtil.isNotEmpty(deviceVoMap) && ObjectUtil.isNotEmpty(deviceVoMap.get(v.getIotId()))) {
                            DeviceVo device = deviceVoMap.get(v.getIotId());
                            //对象拷贝
                            BeanUtil.copyProperties(device, deviceVo);
                            deviceVo.setIotId(deviceVo.getDeviceId());
                        }
                        return deviceVo;
                    }
            ).collect(Collectors.toList());
            //分页
            return PageResponse.of(collect,body.getPage(),body.getPageSize(),(long)body.getPageCount(),(long) body.getTotal());
        }
        return null;
    }

    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) throws Exception {
        request.setIotInstanceId(iotInstanceId);
        QueryDeviceDetailResponse queryDeviceDetailResponse = client.queryDeviceDetail(request);
        if (Boolean.TRUE.equals(queryDeviceDetailResponse.getBody().getSuccess())) {

            QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = queryDeviceDetailResponse.getBody().getData();
            //对象转换  map -> java对象
            DeviceVo deviceVo = BeanUtil.toBean(data, DeviceVo.class);
            List<DeviceVo> devices = deviceMapper.selectByDeviceIds(Lists.newArrayList(data.getIotId()));
            if (CollUtil.isNotEmpty(devices)) {
                //对象拷贝
                BeanUtil.copyProperties(devices.get(0), deviceVo, CopyOptions.create().ignoreNullValue());
                deviceVo.setIotId(deviceVo.getDeviceId());
            }
            return deviceVo;
        }
        throw new BaseException(queryDeviceDetailResponse.getBody().getErrorMessage());
    }

    @Override
    public void deleteDevice(DeleteDeviceRequest request) throws Exception {
        request.setIotInstanceId(iotInstanceId);
        DeleteDeviceResponse response = client.deleteDevice(request);
        if (Boolean.TRUE.equals(response.getBody().getSuccess())) {
            deviceMapper.deleteByDeviceId(request.getIotId());
            return;
        }
        throw new BaseException(response.getBody().getErrorMessage());
    }
}